package com.tg.app.util;

import android.content.Context;
import android.util.Log;

import com.alibaba.sdk.android.oss.ClientConfiguration;
import com.alibaba.sdk.android.oss.ClientException;
import com.alibaba.sdk.android.oss.OSSClient;
import com.alibaba.sdk.android.oss.ServiceException;
import com.alibaba.sdk.android.oss.callback.OSSCompletedCallback;
import com.alibaba.sdk.android.oss.common.OSSLog;
import com.alibaba.sdk.android.oss.common.auth.OSSCredentialProvider;
import com.alibaba.sdk.android.oss.common.auth.OSSFederationCredentialProvider;
import com.alibaba.sdk.android.oss.common.auth.OSSFederationToken;
import com.alibaba.sdk.android.oss.internal.OSSAsyncTask;
import com.alibaba.sdk.android.oss.model.GetObjectRequest;
import com.alibaba.sdk.android.oss.model.GetObjectResult;
import com.tg.app.BuildConfig;
import com.tg.appcommon.android.TGLog;
import com.tange.core.backend.service.http.ClientObserver;
import com.tange.core.backend.service.api.CoreBackendService;
import com.tange.base.toolkit.DateUtil;
import com.tg.data.http.entity.OssTokenBean;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.text.SimpleDateFormat;
import java.util.HashMap;

import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;


public class OssHelper {

    private static final String TAG = "OssHelper";
    private OnGetResult onGetResult;
    private WeakReference<Context> context;
    private OSSAsyncTask task = null;
    private String endpoint = "https://oss-cn-shenzhen.aliyuncs.com";
    private String bucketName = "usingnet-media-cloud-user-private";
    private String rootPath = "";
    private OSSClient ossClient = null;
    private boolean isInit = false;
    private String deviceID;
    private long lastTime;
    private OssResult ossResult;
    private String ossId;

    public OssHelper(Context context, long deviceID, String ossId) {
        this.context = new WeakReference<>(context);
        this.deviceID = deviceID + "";
        this.ossId = ossId;
        getOssToken();
    }

    public long getDownloadTime() {
        return lastTime;
    }

    public void setOnGetResult(OnGetResult onGetResult) {
        this.onGetResult = onGetResult;
    }

    public void setOssResult(OssResult ossResult) {
        this.ossResult = ossResult;
    }

    private void getOssToken() {
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("device_id", deviceID);
        hashMap.put("ossId", ossId);
        CoreBackendService.api().getOssToken(hashMap)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new ClientObserver<OssTokenBean>() {
                    @Override
                    protected void onSuccess(final OssTokenBean content) {
                        bucketName = content.getBucket();
                        endpoint = content.getEndPoint();
                        rootPath = content.getRootPath();
                        new Thread(new Runnable() {
                            @Override
                            public void run() {
                                initOssHelper(content.getAccessKeyId(), content.getAccessKeySecret(), content.getSecurityToken(), content.getExpiration());
                            }
                        }).start();

                    }

                    @Override
                    protected void onResponseError(int errorCode, String errorInfo) {

                    }

                    @Override
                    protected void onOtherError(String error) {

                    }

                    @Override
                    protected void onFinish() {

                    }
                });

    }

    public interface OnGetResult {
        void onGetSuccess(byte[] buf, long time);

        void onGetFailed(String error, int code);
    }

    public interface OssResult {
        void onOssInitSuccess();
    }

    private void initOssHelper(final String accessKeyId, final String accessKeySecret, final String securityToken, final String expiration) {
        if (!isInit) {
            OSSCredentialProvider credentialProvider = new OSSFederationCredentialProvider() {
                @Override
                public OSSFederationToken getFederationToken() {
                    // 您需要在这里实现获取一个FederationToken，并构造成OSSFederationToken对象返回
                    // 如果因为某种原因获取失败，可直接返回nil
                    OSSFederationToken token;
                    // 下面是一些获取token的代码，比如从您的server获取

                    token = new OSSFederationToken(accessKeyId, accessKeySecret, securityToken, expiration);
//
                    return token;
                }
            };
//        OSSCredentialProvider credentialProvider = new OSSAuthCredentialsProvider(stsServer);
            //config
            ClientConfiguration conf = new ClientConfiguration();
            conf.setConnectionTimeout(30 * 1000); // 连接超时时间，默认15秒
            conf.setSocketTimeout(30 * 1000); // Socket超时时间，默认15秒
            conf.setMaxConcurrentRequest(5); // 最大并发请求数，默认5个
            conf.setMaxErrorRetry(2); // 失败后最大重试次数，默认2次
            ossClient = new OSSClient(context.get(), endpoint, credentialProvider, conf);
            if (BuildConfig.DEBUG) {
                OSSLog.enableLog();  //调用此方法即可开启日志
            }
            isInit = true;
            if (this.ossResult != null) {
                this.ossResult.onOssInitSuccess();
            }
        }


    }


    public void getFile(long time) {
        lastTime = time;
        //处理成可以对5整除的数据
        time = DateUtil.getTimestampFiveSec(time);

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd/HH/mm-ss");
        // 拼接下载文件名 如：2019/02/12/12/23-12.data
        String objectKey = String.format("%s/%s.data", rootPath, dateFormat.format(time));

        TGLog.d(TAG, "onScrollStateChanged PlaybackActivity getFile File Name : %s", objectKey);
        // 构造下载文件请求

        if (ossClient == null) {
            // oss异常重新取
            getOssToken();
            return;
        }
        GetObjectRequest request = new GetObjectRequest(bucketName, objectKey);
        final long finalTime = time;
        task = ossClient.asyncGetObject(request, new OSSCompletedCallback<GetObjectRequest, GetObjectResult>() {
            @Override
            public void onSuccess(GetObjectRequest request, GetObjectResult result) {
                InputStream inputStream = result.getObjectContent();//阿里云返回

                BufferedInputStream bis = new BufferedInputStream(inputStream);

                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                try {
                    byte[] buffer = new byte[1024];
                    int len;
                    while ((len = bis.read(buffer)) != -1) {
                        // 处理下载的数据
                        byteArrayOutputStream.write(buffer, 0, len);
                    }
                    byte[] buf = byteArrayOutputStream.toByteArray();
                    bis.close();
                    inputStream.close();
                    byteArrayOutputStream.close();
                    onGetResult.onGetSuccess(buf, finalTime);
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }

            @Override
            public void onFailure(GetObjectRequest request, ClientException clientException, ServiceException serviceException) {
                // 请求异常
                if (clientException != null) {
                    TGLog.d(TAG, "onFailure clientException:");
                    clientException.printStackTrace();
                    // 本地异常如网络异常等
                    if (!clientException.isCanceledException()) {
                        onGetResult.onGetFailed(clientException.getMessage(), -1000);
                    }
                }
                if (serviceException != null) {
                    TGLog.d(TAG, "onFailure   serviceException:");
                    serviceException.printStackTrace();
                    if (serviceException.getStatusCode() == 403) {
                        isInit = false;
                        // oss异常重新取
                        getOssToken();
                    }
                    // 服务异常
                    Log.e("ErrorCode", serviceException.getErrorCode());
                    Log.e("RequestId", serviceException.getRequestId());
                    Log.e("HostId", serviceException.getHostId());
                    Log.e("RawMessage", serviceException.getRawMessage());
                    onGetResult.onGetFailed(serviceException.getErrorCode(), serviceException.getStatusCode());
                }
            }
        });
//        task.waitUntilFinished();//会阻塞线程
    }

    /**
     * 下载当前时间的最新的5s视频  ，即当前时间+5秒
     */
    public long getFileNext() {

        lastTime = lastTime + 5000;
        getFile(lastTime);
        return lastTime;
    }

    public void destroy() {
        cancelTask();
        ossClient = null;
    }

    public void cancelTask() {
        if (task != null)
            task.cancel();
    }

}






